package cn.com.yx.ms.service.impl;

import cn.com.yx.ms.domain.dbmodel.DevHardwareStand;
import cn.com.yx.ms.domain.dbmodel.DevStandRule;
import cn.com.yx.ms.domain.dbmodel.SysDict;
import cn.com.yx.ms.domain.hardware.HardwareConfig;
import cn.com.yx.ms.domain.mq.MessageBase;
import cn.com.yx.ms.domain.mq.MqCommandType;
import cn.com.yx.ms.domain.mq.MqType;
import cn.com.yx.ms.domain.mq.downstream.D_Message4011;
import cn.com.yx.ms.domain.program.CatalogModel;
import cn.com.yx.ms.persistence.DevEquStoreMapper;
import cn.com.yx.ms.persistence.DevHardwareStandMapper;
import cn.com.yx.ms.persistence.DevStandRuleMapper;
import cn.com.yx.ms.service.IDictService;
import cn.com.yx.ms.service.IHardwareService;
import cn.com.yx.ms.service.ISysService;
import cn.yx.framework.configuration.ApiCode;
import cn.yx.framework.configuration.AppConstant;
import cn.yx.framework.configuration.BaseConstant;
import cn.yx.framework.configuration.MyWebSocketInit;
import cn.yx.framework.util.ExcelUtil;
import cn.yx.framework.util.FileUtil;
import cn.yx.framework.util.ZipUtil;
import cn.yx.framework.view.ApiResult;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * ApphubServiceImpl
 */
@Service
@Transactional
public class HardwareImpl implements IHardwareService {

    @Resource
    private DevHardwareStandMapper hardwareStandMapper;
    @Resource
    private DevStandRuleMapper devStandRuleMapper;
    @Resource
    private DevEquStoreMapper devEquStoreMapper;
    @Resource
    private IDictService iDictService;

    @Override
    public ApiCode generateHardwareSn(String areacode, String projectNo) {
        return null;
    }

    @Override
    public ApiCode importHardWareAndStand(HttpServletRequest request) {
        return null;
    }

    @Override
    public ApiCode manualSaveHardWareAndStand(String hardwareno, String standname) {
        return null;
    }

    @Override
    public ApiCode syncHardwareAndEquStore() {
        return null;
    }

    @Override
    public ApiCode importStandRule(HttpServletRequest request) {
        return null;
    }

    @Override
    public DevStandRule findRule() {
        return null;
    }

    @Override
    public ApiCode pushDevConfig(String hardwareSn) throws Exception {

        ApiCode apiCode = ApiCode.APP_100200;
        HardwareConfig hardwareConfig = findOne(hardwareSn);

        MessageBase<D_Message4011> message4010 = new MessageBase<>();
        message4010.setMsgid(UUID.randomUUID().toString());
        message4010.setDeviceid(hardwareSn);
        message4010.setCommand(MqCommandType.C4011.getIndex());
        message4010.setType(MqType.response.getName());
        message4010.setStatus("200");

        D_Message4011 content = new D_Message4011();
        content.setDeviceId(hardwareConfig.getDeviceId()); // 设备编号
        content.setHttpUrl(hardwareConfig.getHttpUrl()); //资源下载路径
        content.setUpdateUrl(hardwareConfig.getUpdateUrl()); //更新包版本比对路径
        content.setWsUrl(hardwareConfig.getWsUrl()); // ws业务通道
        content.setWsForUpdateUrl(hardwareConfig.getWsForUpdateUrl()); // ws升级通道
        message4010.setContent(content);
        MyWebSocketInit.sendInfo(hardwareSn, JSON.toJSONString(message4010));
        return apiCode;
    }

    @Override
    public HardwareConfig findOne(String hardwareno) {
        HardwareConfig hardwareConfig = null;
        DevHardwareStand devHardwareStand = hardwareStandMapper.selectByPrimaryKey(hardwareno);
        if (devHardwareStand != null) {
            hardwareConfig = (HardwareConfig) JSON.parse(devHardwareStand.getContent());
        }

        // 如果设备配置为空，则用公共设备配置赋值并写入设备content
        if (hardwareConfig == null) {
            hardwareConfig = new HardwareConfig();
            List<SysDict> sysDicts = iDictService.findAllDictDatas("D1003");
            hardwareConfig.setDeviceId(devHardwareStand.getEquipmentno());
            for (int i = 0; i < sysDicts.size(); i++) {
                if (StringUtils.contains(sysDicts.get(i).getDictdataname(), "wsUrl"))
                    hardwareConfig.setWsUrl(sysDicts.get(i).getDictdataname());

                if (StringUtils.contains(sysDicts.get(i).getDictdataname(), "wsForUpdateUrl"))
                    hardwareConfig.setWsForUpdateUrl(sysDicts.get(i).getDictdataname());

                if (StringUtils.contains(sysDicts.get(i).getDictdataname(), "httpUrl"))
                    hardwareConfig.setHttpUrl(sysDicts.get(i).getDictdataname());

                if (StringUtils.contains(sysDicts.get(i).getDictdataname(), "updateUrl"))
                    hardwareConfig.setUpdateUrl(sysDicts.get(i).getDictdataname());
            }
        }

        return hardwareConfig;
    }

    /**
     * 导入施工站台和板卡序列号
     *
     * @param request 导入板卡信息
     * @return
     */
    @Override
    public ApiResult importHardWare(HttpServletRequest request) {
        ApiResult apiResult = new ApiResult();
        apiResult.setSucc(false);

        String fileSavePath = BaseConstant.getUploadConfig().getFilepath() + "/template";

        String fileName = "";

        //request强制转换注意
        MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;

        // 将文件保存到指定目录
        if (mRequest != null) {
            try {
                fileName = mRequest.getFile("file").getOriginalFilename();
//                File fileForZip = new File(fileSavePath + "/" + fileName);
//                FileUtils.copyFile(fileForZip, (File)mRequest.getFile("file"));

                // 将上传zip文件保存到临时目录
                FileUtil.writeFile(fileSavePath,
                        fileName,
                        mRequest.getFile("file").getBytes());

                // 从file中直接读取字节流
                MultipartFile mfile = mRequest.getFile("file");
                byte[] bytes = mfile.getBytes();
                FileOutputStream fs = new FileOutputStream(fileSavePath + "/" + fileName);
                fs.write(bytes);
                fs.close();

                Workbook wb = ExcelUtil.createWb(fileSavePath + "/" + fileName);
                Sheet sheet = ExcelUtil.getSheet(wb, 0);

                // 遍历Sheet
                List<Object[]> lineList = ExcelUtil.listFromSheet(sheet);

                // Sheet中只有一行标题或没有行
                if (lineList.size() <= 1) {
                    return new ApiResult().failure(AppConstant.MSG_FAILURE, "文件中内容为空", null);
                }

                List<DevHardwareStand> list = new ArrayList<DevHardwareStand>();

                // 循环读取行
                for (int line = 1; line < lineList.size(); line++) {
                    DevHardwareStand devHardwareStand = new DevHardwareStand();

                    // 空行
                    if (lineList.get(line) == null) {
                        continue;
                    }

                    //Excel 导入数据
                    if (null == lineList.get(line)[1]) {
                        return new ApiResult().failure(AppConstant.MSG_FAILURE, "板卡序列号不能为空", null);
                    } else {
                        if (spliteString(lineList.get(line)[1].toString()).indexOf("-") == -1 || spliteString(lineList.get(line)[1].toString()).split("-").length - 1 != 3) {
                            return new ApiResult().failure(AppConstant.MSG_FAILURE, "板卡序列号:" + spliteString(lineList.get(line)[1].toString()) + "不符合规范", null);
                        }

                        if (null != hardwareStandMapper.selectByPrimaryKey(spliteString(lineList.get(line)[1].toString()))) {
                            return new ApiResult().failure(AppConstant.MSG_FAILURE, "板卡序列号:" + spliteString(lineList.get(line)[1].toString()) + "已存在，请确认", null);
                        }
                        devHardwareStand.setHardwareUniqueNo(spliteString(lineList.get(line)[1].toString()));
                    }

                    if (null == lineList.get(line)[2]) {
                        return new ApiResult().failure(AppConstant.MSG_FAILURE, "站台名称不能为空", null);
                    } else {
                        devHardwareStand.setStandname(spliteString(lineList.get(line)[2].toString()));
                    }

                    // 施工方导入时间
                    devHardwareStand.setImporttime(new Date());

                    // 同步标识
                    devHardwareStand.setSync(0);
                    list.add(devHardwareStand);
                }

                // 板卡信息及施工站台信息导入
                if (hardwareStandMapper.insertDevHardWareList(list) == list.size()) {
                    apiResult.setSucc(true);
                }

                // 是否存在规则库
                if (devStandRuleMapper.selectRuleCount() > 0) {
                    // 存在的场合,同步设备表
                    for (DevHardwareStand devHardwareStand : list) {
                        if (sync(devHardwareStand.getHardwareUniqueNo()) == null) {
                            return new ApiResult().failure(AppConstant.MSG_FAILURE, "序列号:" + devHardwareStand.getHardwareUniqueNo() + "同步失败", null);
                        }
                    }

                } else {
                    // 不存在的场合,导入板卡序列号及施工站台
                }
            } catch (Exception ex) {
                return new ApiResult().failure(AppConstant.MSG_FAILURE, "板卡信息导入失败", null);
            }
        } else {
            return new ApiResult().failure(AppConstant.MSG_FAILURE, "文件读取失败", null);
        }
        return apiResult;
    }

    /**
     * 同步规则库
     *
     * @param hardwareUniqueNo 序列号
     */
    private String sync(String hardwareUniqueNo) {
        String equipmentno = devStandRuleMapper.selectByHardWareNo(hardwareUniqueNo);

        // 更新设备表
        if (StringUtils.isNotEmpty(equipmentno)) {
            int rt = devEquStoreMapper.updateByHardWareNo(equipmentno, hardwareUniqueNo);

            if (rt > 0) {
                // 板卡物理信息表更新
                DevHardwareStand devHardwareStand = new DevHardwareStand();
                devHardwareStand.setSync(1);
                devHardwareStand.setSynctime(new Date());

                rt = hardwareStandMapper.updateByPrimaryKey(devHardwareStand);

                if (rt > 0) {
                    return equipmentno;
                }
            }
        }
        return null;
    }

    /**
     * 分割字符串（分隔符：[）
     *
     * @param
     * @return
     */
    private String spliteString(String fromString) {
        String toString = fromString.substring(0, fromString.indexOf('['));
        return toString;
    }

    /**
     * 获取站台目录数据
     *
     * @return
     */
    @Override
    public List<CatalogModel> getHardWares() {

        List<DevHardwareStand> list = hardwareStandMapper.selectStandName();
        List<CatalogModel> devCatalogModels = new ArrayList<CatalogModel>();
        //初始化根节点
        CatalogModel root = new CatalogModel();
        root.setId("root");
        root.setName("站台设备");
        root.setNumber("");
        root.setChildren(new ArrayList<CatalogModel>());

        for (DevHardwareStand devHardwareStand : list) {
            CatalogModel child = new CatalogModel();
            child.setId(devHardwareStand.getHardwareUniqueNo());
            child.setName(devHardwareStand.getStandname() + "(" + devHardwareStand.getHardwareUniqueNo() + ")");
            child.setParentid("root");
            root.getChildren().add(child);
        }
        devCatalogModels.add(root);
        return devCatalogModels;
    }

    /**
     * 同步站台设备
     *
     * @param hardwareuniqueno 设备序列号
     * @return
     */
    @Override
    public ApiResult hardwareSync(String hardwareuniqueno) {
        ApiResult apiResult = new ApiResult();

        // 检查是否已经同步过
        DevHardwareStand devHardwareStand = hardwareStandMapper.selectByHardwareUniqueNo(hardwareuniqueno);

        if (null == devHardwareStand) {
            devHardwareStand = new DevHardwareStand();
            devHardwareStand.setHardwareUniqueNo(hardwareuniqueno);
            apiResult.setData(devHardwareStand);
            apiResult.setSucc(false);
            apiResult.setMsg("序列号:" + hardwareuniqueno + "的规则表还未生成,请联系管理员!");
            return apiResult;
        }

        // 已经同步的场合。
        devHardwareStand.setHardwareUniqueNo(hardwareuniqueno);
        if (1 == devHardwareStand.getSync()) {
            apiResult.setSucc(true);
            apiResult.setData(devHardwareStand);
            return apiResult;
        }

        // 未同步的场合
        String equipmentno = sync(hardwareuniqueno);
        if (equipmentno == null) {
            apiResult.setSucc(false);
            apiResult.setData(devHardwareStand);
            apiResult.setMsg("序列号:" + hardwareuniqueno + "同步失败!");
            return apiResult;
        }
        devHardwareStand.setEquipmentno(equipmentno);
        apiResult.setData(devHardwareStand);
        apiResult.setSucc(true);
        return apiResult;
    }

    @Override
    public List<DevHardwareStand> findDatas() {
        return hardwareStandMapper.selectStandName();
    }
}